package com.dj.mingkong.admin.biz.scheduler;

import com.dj.mingkong.admin.biz.enums.GenStatusEnum;
import com.dj.mingkong.admin.biz.repository.database.music.AlbumRepository;
import com.dj.mingkong.admin.biz.repository.database.music.BoxRepository;
import com.dj.mingkong.admin.biz.repository.database.music.MusicRepository;
import com.dj.mingkong.admin.biz.repository.database.music.MusicianRepository;
import com.dj.mingkong.admin.biz.repository.database.system.UserRepository;
import com.dj.mingkong.common.constant.RedisConstants;
import com.dj.mingkong.common.infrastructure.eo.database.music.AlbumEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicianEo;
import com.dj.mingkong.common.infrastructure.eo.database.system.UserEo;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Set;

/**
 * 人气同步更新任务
 *
 * @author zenglonghui
 * @date: 2022/10/17 14:42
 */
@Slf4j
@Component
public class PopularitySyncJob {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private AlbumRepository albumRepository;
    @Resource
    private MusicianRepository musicianRepository;
    @Resource
    private MusicRepository musicRepository;
    @Resource
    private UserRepository userRepository;
    @Resource
    private BoxRepository boxRepository;

    /**
     * 更新专辑人气
     */
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("syncAlbumPopularityJob")
    public void syncAlbumPopularityJob() {
        XxlJobHelper.log("syncAlbumPopularityJob start......");
        log.info("album updatePopularity start......");
        final Set<Object> keys = redisTemplate.boundHashOps(RedisConstants.POPULARITY_ALBUM).keys();
        if (CollectionUtils.isNotEmpty(keys)) {
            XxlJobHelper.log("album keys size:{}", keys.size());
            log.info("album keys size:{}", keys.size());
            for (Object key : keys) {
                final Long popularity = redisTemplate.boundHashOps(RedisConstants.POPULARITY_ALBUM)
                        .increment(key, 0);
                if (Objects.nonNull(popularity)) {
                    final Long id = Long.valueOf(key.toString());
                    final AlbumEo albumEo = albumRepository.getById(id);
                    if (Objects.isNull(albumEo)) {
                        continue;
                    }
                    albumEo.setPopularity(Long.sum(albumEo.getPopularity(), popularity))
                            .setGenStatus(GenStatusEnum.WAIT.getIntVal());
                    albumRepository.updateById(albumEo);
                    XxlJobHelper.log("update successfully, id:{}, popularity:{}", id, popularity);
                    log.info("update successfully, id:{}, popularity:{}", id, popularity);
                }
            }
        }
        redisTemplate.delete(RedisConstants.POPULARITY_ALBUM);
        log.info("album updatePopularity end......");
        XxlJobHelper.log("syncAlbumPopularityJob end......");
    }

    /**
     * 更新音乐人人气
     */
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("syncMusicianPopularityJob")
    public void syncMusicianPopularityJob() {
        XxlJobHelper.log("syncMusicianPopularityJob start......");
        log.info("musician updatePopularity start......");
        final Set<Object> keys = redisTemplate.boundHashOps(RedisConstants.POPULARITY_MUSICIAN).keys();
        if (CollectionUtils.isNotEmpty(keys)) {
            XxlJobHelper.log("musician keys size:{}", keys.size());
            log.info("musician keys size:{}", keys.size());
            for (Object key : keys) {
                final Long popularity = redisTemplate.boundHashOps(RedisConstants.POPULARITY_MUSICIAN)
                        .increment(key, 0);
                if (Objects.nonNull(popularity)) {
                    final Long id = Long.valueOf(key.toString());
                    final MusicianEo musicianEo = musicianRepository.getById(id);
                    if (Objects.isNull(musicianEo)) {
                        continue;
                    }
                    musicianEo.setPopularity(Long.sum(musicianEo.getPopularity(), popularity))
                            .setGenStatus(GenStatusEnum.WAIT.getIntVal());
                    musicianRepository.updateById(musicianEo);
                    XxlJobHelper.log("update successfully, id:{}, popularity:{}", id, popularity);
                    log.info("update successfully, id:{}, popularity:{}", id, popularity);
                }
            }
        }
        redisTemplate.delete(RedisConstants.POPULARITY_MUSICIAN);
        log.info("musician updatePopularity end......");
        XxlJobHelper.log("syncMusicianPopularityJob end......");
    }

    /**
     * 更新音乐播放人气
     */
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("syncMusicPopularityJob")
    public void syncMusicPopularityJob() {
        XxlJobHelper.log("syncMusicPopularityJob start......");
        log.info("music updatePopularity start......");
        final Set<Object> keys = redisTemplate.boundHashOps(RedisConstants.POPULARITY_MUSIC).keys();
        if (CollectionUtils.isNotEmpty(keys)) {
            XxlJobHelper.log("music keys size:{}", keys.size());
            log.info("music keys size:{}", keys.size());
            for (Object key : keys) {
                final Long popularity = redisTemplate.boundHashOps(RedisConstants.POPULARITY_MUSIC)
                        .increment(key, 0);
                if (Objects.nonNull(popularity)) {
                    final Long id = Long.valueOf(key.toString());
                    final MusicEo musicEo = musicRepository.getById(id);
                    if (Objects.isNull(musicEo)) {
                        continue;
                    }
                    musicEo.setPopularity(Long.sum(musicEo.getPopularity(), popularity))
                            .setGenStatus(GenStatusEnum.WAIT.getIntVal());
                    musicRepository.updateById(musicEo);
                    XxlJobHelper.log("update successfully, id:{}, popularity:{}", id, popularity);
                    log.info("update successfully, id:{}, popularity:{}", id, popularity);
                }
            }
        }
        redisTemplate.delete(RedisConstants.POPULARITY_MUSIC);
        log.info("music updatePopularity end......");
        XxlJobHelper.log("syncMusicPopularityJob end......");
    }

    /**
     * 更新用户人气
     */
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("syncUserPopularityJob")
    public void syncUserPopularityJob() {
        XxlJobHelper.log("syncUserPopularityJob start......");
        log.info("user updatePopularity start......");
        final Set<Object> keys = redisTemplate.boundHashOps(RedisConstants.POPULARITY_USER).keys();
        if (CollectionUtils.isNotEmpty(keys)) {
            XxlJobHelper.log("user keys size:{}", keys.size());
            log.info("user keys size:{}", keys.size());
            for (Object key : keys) {
                final Long popularity = redisTemplate.boundHashOps(RedisConstants.POPULARITY_USER)
                        .increment(key, 0);
                if (Objects.nonNull(popularity)) {
                    final Long id = Long.valueOf(key.toString());
                    final UserEo userEo = userRepository.getById(id);
                    if (Objects.isNull(userEo)) {
                        continue;
                    }
                    userEo.setPopularity(Long.sum(userEo.getPopularity(), popularity))
                            .setGenStatus(GenStatusEnum.WAIT.getIntVal());
                    userRepository.updateById(userEo);
                    XxlJobHelper.log("update successfully, id:{}, popularity:{}", id, popularity);
                    log.info("update successfully, id:{}, popularity:{}", id, popularity);
                }
            }
        }
        redisTemplate.delete(RedisConstants.POPULARITY_USER);
        log.info("user updatePopularity end......");
        XxlJobHelper.log("syncUserPopularityJob end......");
    }

    /**
     * 更新音乐盒人气
     */
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("syncBoxPopularityJob")
    public void syncBoxPopularityJob() {
        XxlJobHelper.log("syncBoxPopularityJob start......");
        log.info("box updatePopularity start......");
        final Set<Object> keys = redisTemplate.boundHashOps(RedisConstants.POPULARITY_BOX).keys();
        if (CollectionUtils.isNotEmpty(keys)) {
            XxlJobHelper.log("box keys size:{}", keys.size());
            log.info("box keys size:{}", keys.size());
            for (Object key : keys) {
                final Long popularity = redisTemplate.boundHashOps(RedisConstants.POPULARITY_BOX)
                        .increment(key, 0);
                if (Objects.nonNull(popularity)) {
                    final Long id = Long.valueOf(key.toString());
                    final BoxEo boxEo = boxRepository.getById(id);
                    if (Objects.isNull(boxEo)) {
                        continue;
                    }
                    boxEo.setPopularity(Long.sum(boxEo.getPopularity(), popularity))
                            .setGenStatus(GenStatusEnum.WAIT.getIntVal());
                    boxRepository.updateById(boxEo);
                    XxlJobHelper.log("update successfully, id:{}, popularity:{}", id, popularity);
                    log.info("update successfully, id:{}, popularity:{}", id, popularity);
                }
            }
        }
        redisTemplate.delete(RedisConstants.POPULARITY_BOX);
        log.info("box updatePopularity end......");
        XxlJobHelper.log("syncBoxPopularityJob end......");
    }
}
